<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { fetchAddUser, fetchGetAllRoles, fetchGetDeptTree, fetchGetPostList, fetchUpdateUser } from '@/service/api';
import { $t } from '@/locales';
import { enableStatusOptions, genderOptions } from '@/constants/business';

defineOptions({
  name: 'UserOperateModal'
});

interface Props {
  /** the type of operation */
  operateType: NaiveUI.TableOperateType;
  /** the edit row data */
  rowData?: Api.SystemManage.User | null;
}

const props = defineProps<Props>();

interface Emits {
  (e: 'submitted'): void;
}

const emit = defineEmits<Emits>();

const visible = defineModel<boolean>('visible', {
  default: false
});

const { formRef, validate, restoreValidation } = useNaiveForm();
const { defaultRequiredRule } = useFormRules();

const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: $t('page.manage.user.addUser'),
    edit: $t('page.manage.user.editUser')
  };
  return titles[props.operateType];
});

type Model = {
  userName: string;
  displayName: string;
  loginName: string;
  gender: Api.SystemManage.gender | null;
  nickName: string;
  address: string;
  age: string;
  telephone: string;
  email: string;
  idNumber: string;
  birthday: string;
  userRole: number | null; // 改为单个数字，存储角色ID
  userDept: number | null; // 用户所属部门ID
  userPost: number | null; // 用户岗位ID
  status: Api.Common.EnableStatus;
};

const model: any = reactive(createDefaultModel());

function createDefaultModel(): Model {
  return {
    userName: '',
    displayName: '',
    loginName: '',
    gender: null,
    nickName: '',
    address: '',
    age: '',
    telephone: '',
    email: '',
    idNumber: '',
    birthday: '',
    userRole: null,
    userDept: null,
    userPost: null,
    // 默认启用
    status: 1
  };
}

type RuleKey = Extract<keyof Model, 'userName' | 'status'>;

const rules: Record<RuleKey, App.Global.FormRule> = {
  userName: defaultRequiredRule,
  status: defaultRequiredRule
};

/** the enabled role options */
const roleOptions = ref<CommonType.Option<number>[]>([]);

/** the department tree options */
const deptTreeOptions = ref<Api.SystemManage.DeptTree[]>([]);

/** the position options */
const positionOptions = ref<CommonType.Option<number>[]>([]);

/** loading states */
const roleLoading = ref(false);
const deptLoading = ref(false);
const positionLoading = ref(false);

async function getRoleOptions() {
  try {
    roleLoading.value = true;
    const { error, data } = await fetchGetAllRoles();

    if (!error && data) {
      roleOptions.value = data.map(item => ({
        label: item.roleName,
        value: item.roleId
      }));
    } else {
      window.$message?.error($t('common.operationFailed'));
      roleOptions.value = [];
    }
  } catch (err) {
    window.$message?.error($t('common.operationFailed'));
    roleOptions.value = [];
  } finally {
    roleLoading.value = false;
  }
}

async function getDeptTreeOptions() {
  try {
    deptLoading.value = true;
    const { error, data } = await fetchGetDeptTree();

    if (!error && data) {
      deptTreeOptions.value = data;
    } else {
      window.$message?.error($t('common.operationFailed'));
      deptTreeOptions.value = [];
    }
  } catch (err) {
    window.$message?.error($t('common.operationFailed'));
    deptTreeOptions.value = [];
  } finally {
    deptLoading.value = false;
  }
}

async function getPositionOptions() {
  try {
    positionLoading.value = true;
    const { error, data } = await fetchGetPostList();

    if (!error && data) {
      positionOptions.value = data.map(item => ({
        label: item.postName,
        value: item.postId
      }));
    } else {
      window.$message?.error($t('common.operationFailed'));
      positionOptions.value = [];
    }
  } catch (err) {
    window.$message?.error($t('common.operationFailed'));
    positionOptions.value = [];
  } finally {
    positionLoading.value = false;
  }
}

// 递归转换部门树为选项格式
function convertDeptTreeToOptions(deptTree: Api.SystemManage.DeptTree[]): CommonType.Option<number>[] {
  const options: CommonType.Option<number>[] = [];

  function processDept(dept: Api.SystemManage.DeptTree, level: number = 0) {
    const prefix = '　'.repeat(level); // 使用全角空格作为缩进
    options.push({
      label: `${prefix}${dept.deptName}`,
      value: dept.deptId
    });

    if (dept.children && dept.children.length > 0) {
      dept.children.forEach(child => processDept(child, level + 1));
    }
  }

  deptTree.forEach(dept => processDept(dept));
  return options;
}

const deptOptions = computed(() => convertDeptTreeToOptions(deptTreeOptions.value));

// eslint-disable-next-line complexity
function handleInitModel() {
  Object.assign(model, createDefaultModel());

  if (props.operateType === 'edit' && props.rowData) {
    // 处理编辑时的数据映射
    const editData = { ...(props.rowData as any) };

    // 处理用户角色数据 - 支持从复数字段名映射到单数字段名
    const roleData = editData.userRole || editData.userRoles;
    if (roleData !== undefined && roleData !== null) {
      if (Array.isArray(roleData)) {
        // 如果是数组，取第一个有效值
        const roleId = roleData
          .map((role: any) => (typeof role === 'string' ? Number.parseInt(role, 10) : Number(role)))
          .filter((id: any) => !Number.isNaN(id) && id > 0)[0];
        editData.userRole = roleId || null;
      } else if (typeof roleData === 'string') {
        const roleId = Number.parseInt(roleData, 10);
        editData.userRole = !Number.isNaN(roleId) && roleId > 0 ? roleId : null;
      } else {
        const roleId = Number(roleData);
        editData.userRole = !Number.isNaN(roleId) && roleId > 0 ? roleId : null;
      }
    } else {
      editData.userRole = null;
    }

    // 处理部门数据 - 支持从复数字段名映射到单数字段名
    const deptData = editData.userDept || editData.userDepts;
    if (deptData !== undefined && deptData !== null) {
      if (Array.isArray(deptData)) {
        // 如果是数组，取第一个有效值
        const deptId = deptData
          .map((dept: any) => (typeof dept === 'string' ? Number.parseInt(dept, 10) : Number(dept)))
          .filter((id: any) => !Number.isNaN(id) && id > 0)[0];
        editData.userDept = deptId || null;
      } else if (typeof deptData === 'string') {
        const deptId = Number.parseInt(deptData, 10);
        editData.userDept = !Number.isNaN(deptId) && deptId > 0 ? deptId : null;
      } else {
        const deptId = Number(deptData);
        editData.userDept = !Number.isNaN(deptId) && deptId > 0 ? deptId : null;
      }
    } else {
      editData.userDept = null;
    }

    // 处理岗位数据 - 支持从复数字段名映射到单数字段名
    const postData = editData.userPost || editData.userPosts;
    if (postData !== undefined && postData !== null) {
      if (Array.isArray(postData)) {
        // 如果是数组，取第一个有效值
        const postId = postData
          .map((post: any) => (typeof post === 'string' ? Number.parseInt(post, 10) : Number(post)))
          .filter((id: any) => !Number.isNaN(id) && id > 0)[0];
        editData.userPost = postId || null;
      } else if (typeof postData === 'string') {
        const postId = Number.parseInt(postData, 10);
        editData.userPost = !Number.isNaN(postId) && postId > 0 ? postId : null;
      } else {
        const postId = Number(postData);
        editData.userPost = !Number.isNaN(postId) && postId > 0 ? postId : null;
      }
    } else {
      editData.userPost = null;
    }

    // 清理旧的复数字段名
    delete editData.userRoles;
    delete editData.userDepts;
    delete editData.userPosts;

    // 使用类型断言绕过类型检查
    const processedData = editData as any;
    Object.assign(model, processedData);
  }
}

function closeModal() {
  visible.value = false;
}

async function handleSubmit() {
  await validate();

  // 构建提交数据
  const submitData = {
    ...model,
    // 确保ID字段正确
    id: props.operateType === 'edit' ? props.rowData?.id || 0 : 0
  } as any;

  try {
    const apiFunction = props.operateType === 'add' ? fetchAddUser : fetchUpdateUser;
    const { error } = await apiFunction(submitData);

    if (!error) {
      window.$message?.success($t('common.updateSuccess'));
      closeModal();
      emit('submitted');
    } else {
      window.$message?.error($t('common.operationFailed'));
    }
  } catch (err) {
    window.$message?.error($t('common.operationFailed'));
  }
}

watch(visible, async () => {
  if (visible.value) {
    await restoreValidation();

    // 先并行加载所有选项数据
    await Promise.all([getRoleOptions(), getDeptTreeOptions(), getPositionOptions()]);

    // 数据加载完成后再初始化模型
    handleInitModel();
  }
});
</script>

<template>
  <NModal v-model:show="visible" preset="dialog" :title="title" style="width: 900px; max-width: 90vw">
    <NForm ref="formRef" :model="model" :rules="rules" label-placement="left" :label-width="100">
      <NGrid :cols="2" :x-gap="16">
        <NFormItemGi :label="$t('page.manage.user.userName')" path="userName">
          <NInput v-model:value="model.userName" :placeholder="$t('page.manage.user.form.userName')" />
        </NFormItemGi>

        <NFormItemGi :label="$t('page.manage.user.displayName')" path="displayName">
          <NInput v-model:value="model.displayName" :placeholder="$t('page.manage.user.form.displayName')" />
        </NFormItemGi>

        <NFormItemGi :label="$t('page.manage.user.gender')" path="gender">
          <NRadioGroup v-model:value="model.gender">
            <NRadio v-for="item in genderOptions" :key="item.value" :value="item.value" :label="$t(item.label)" />
          </NRadioGroup>
        </NFormItemGi>

        <NFormItemGi :label="$t('page.manage.user.status')" path="status">
          <NRadioGroup v-model:value="model.status">
            <NRadio v-for="item in enableStatusOptions" :key="item.value" :value="item.value" :label="$t(item.label)" />
          </NRadioGroup>
        </NFormItemGi>

        <NFormItemGi :label="$t('page.manage.user.nickName')" path="nickName">
          <NInput v-model:value="model.nickName" :placeholder="$t('page.manage.user.form.nickName')" />
        </NFormItemGi>

        <NFormItemGi :label="$t('page.manage.user.telephone')" path="telephone">
          <NInput v-model:value="model.telephone" :placeholder="$t('page.manage.user.form.telephone')" />
        </NFormItemGi>

        <NFormItemGi :label="$t('page.manage.user.email')" path="email">
          <NInput v-model:value="model.email" :placeholder="$t('page.manage.user.form.email')" />
        </NFormItemGi>

        <NFormItemGi :label="$t('page.manage.user.address')" path="address">
          <NInput v-model:value="model.address" :placeholder="$t('page.manage.user.form.address')" />
        </NFormItemGi>

        <NFormItemGi :label="$t('page.manage.user.idNumber')" path="idNumber">
          <NInput v-model:value="model.idNumber" :placeholder="$t('page.manage.user.form.idNumber')" />
        </NFormItemGi>

        <!-- 用户角色选择 -->
        <NFormItemGi :label="$t('page.manage.user.userRole')" path="userRole">
          <NSelect
            :key="`role-${visible}-${roleOptions.length}`"
            v-model:value="model.userRole"
            :options="roleOptions"
            :loading="roleLoading"
            placeholder="请选择角色"
            clearable
            value-field="value"
            label-field="label"
          />
        </NFormItemGi>

        <!-- 用户部门选择 -->
        <NFormItemGi :label="$t('page.manage.user.belongDept')" path="userDept">
          <NSelect
            :key="`dept-${visible}-${deptOptions.length}`"
            v-model:value="model.userDept"
            :options="deptOptions"
            :loading="deptLoading"
            placeholder="请选择部门"
            clearable
            value-field="value"
            label-field="label"
          />
        </NFormItemGi>

        <!-- 用户岗位选择 -->
        <NFormItemGi :label="$t('page.manage.user.userPost')" path="userPost">
          <NSelect
            :key="`post-${visible}-${positionOptions.length}`"
            v-model:value="model.userPost"
            :options="positionOptions"
            :loading="positionLoading"
            placeholder="请选择岗位"
            clearable
            value-field="value"
            label-field="label"
          />
        </NFormItemGi>
      </NGrid>
    </NForm>

    <template #action>
      <NSpace>
        <NButton @click="closeModal">{{ $t('common.cancel') }}</NButton>
        <NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
      </NSpace>
    </template>
  </NModal>
</template>

<style scoped></style>
